home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 8 / Night Owl CD-ROM (NOPV8) (Night Owl Publisher) (1993).ISO / 047a / lex_yacc.arj / LEXLIB.PAS < prev    next >
Pascal/Delphi Source File  |  1990-01-14  |  9KB  |  228 lines

  1.  
  2. unit LexLib;
  3.   (* Library of supplementing routines for Lex generated lexical analysers.
  4.      V1.1 9-29-88 AG
  5.      V2.0 2-28-89, 5-28-89 AG *)
  6.  
  7.   interface
  8.  
  9.   (* The Lex library defines
  10.      - the default input and output streams to be used by a generated
  11.        lexical analyser yylex (these defaults may be overwritten by
  12.        appropriate declarations in the user program or Lex specification)
  13.      - the default yylex error handler yyloverflow; this routine can be
  14.        overwritten by an appropriate user-defined procedure *)
  15.  
  16.   (* Default I/O streams: **************************************************)
  17.  
  18.   (* The default input/output streams are implemented as Pascal text files
  19.      that are initialized to read from standard input and write to standard
  20.      output, allowing for DOS I/O redirection and piping. The I/O streams may
  21.      also be redirected and manipulated by using the appropriate Turbo Pascal
  22.      file routines (assign, reset, rewrite, close, ...) on yyin and yyout.
  23.      Furthermore, if the I/O streams to be used are something other
  24.      than MS-DOS files and devices (e.g. internal memory), the procedures
  25.      listed below can be replaced altogether by suitable user defined
  26.      routines with compatible specifications, since yylex uses only the
  27.      routines input, output, unput and yywrap and does not access the
  28.      I/O files directly.
  29.      yyin and yyout are closed automatically at the end of the main
  30.      program; however, if you want to process multiple files in sequence, you
  31.      will have to close, reassign and reopen the files explicitly (and also
  32.      reinitialize yylineno appropriately, if you intend to use it).
  33.      Error handling: the result of the latest LexLib I/O operation is stored
  34.      in the yyioresult variable; in case of an error (yyioresult<>0) yyin will
  35.      return #0 (end-of-file).
  36.      A nonzero value of yyioresult can be used to determine the nature of an
  37.      error (refer to the description of `ioresult' in the Turbo Pascal
  38.      documentation). *)
  39.  
  40.   var
  41.     yyin, yyout : Text;
  42.     (* default I/O streams; initialized to standard input and output *)
  43.     yyioresult : integer;
  44.     (* result of last I/O operation *)
  45.     yylineno : integer;
  46.     (* current line number, initialized to 1 and updated automatically
  47.        by input and unput *)
  48.   function input : char;
  49.     (* read a character from the input stream; return #0 for
  50.        end-of-file; convert line end (<CR><LF>) to newline (\n) *)
  51.   procedure output(c : char);
  52.     (* write a character on the output stream; convert newline (\n) to
  53.        <CR><LF> *)
  54.   procedure unput(c : char);
  55.     (* return c to the input stream to be reread by subsequent calls to
  56.        yyin; the current implementation of unput is restricted to
  57.        255 characters max; if this restriction is violated unput will
  58.        call LexLib.yyloverflow *)
  59.   function yywrap : boolean;
  60.     (* this routine is called by yylex at end of input to determine whether
  61.        to terminate lexical analysis and perform the normal wrapup (return
  62.        end-of-file, etc.); the standard version of yywrap always returns
  63.        TRUE, indicating that yylex should perform normal wrapup.
  64.        This routine may be redefined to do application dependent processing
  65.        at end-of-file; in particular, it can arrange for more input and
  66.        return FALSE in which case yylex will continue lexical analysis. *)
  67.  
  68.   (* Error handler: ********************************************************)
  69.  
  70.   function yyloverflow : boolean;
  71.     (* Called by yylex in case of input buffer overflow; this default version
  72.        prints an error message and returns TRUE indicating a non-recoverable
  73.        overflow which causes yylex to terminate the program with errorlevel 1.
  74.        yyloverflow may be redefined to print a more appropriate error message,
  75.        or do some other processing. In particular, it may inspect and
  76.        manipulate the input stream (e.g. insert a character that will
  77.        terminate the current match), and return FALSE to yylex, in which case
  78.        yylex will automatically recover from the overflow error (yylex will
  79.        obtain the next input character, and if that character does not
  80.        already terminate the match, will append the character to the match
  81.        and assume that now the next input character cannot be accepted).
  82.        NOTE: This routine is *nonstandard*, i.e. not provided by UNIX Lex
  83.          versions. *)
  84.  
  85.   (* procedures and variables defined by yylex: ****************************)
  86.  
  87.   (* the following user procedures and variables are not defined by the Lex
  88.      library, but are declared directly in the Lex output file (they are
  89.      compatible with the corresponding UNIX Lex routines and macros):
  90.      var
  91.        yytext : string[yylbufsize];
  92.          { text of token previously matched by yylex }
  93.        yyleng : Byte;
  94.          { current length of yytext (last character in yytext is
  95.            yytext[yyleng]) }
  96.      procedure yymore;
  97.        { extend the current match by appending the next match to the current
  98.          token in yytext }
  99.      procedure yyless(n : integer);
  100.        { only retain the first n characters from the current match in yytext;
  101.          return all other characters to the input stream }
  102.      procedure reject;
  103.        { reject the current match and process whatever rule was second
  104.          choice after the current rule; this routine may be used to detect
  105.          items that overlap or include each other }
  106.      procedure begin_(s : integer);
  107.        { put yylex in start state s (0: initial start state; <id>: start
  108.          state defined by %start <id> declaration (note the underscore
  109.          at the end of the name of this routine!) }
  110.      procedure return(tok : integer);
  111.        { sets tok as the return value for yylex and causes yylex to exit
  112.          as soon as all actions of the current rule have been executed (to
  113.          exit from an action - but not automatically from yylex -, the Turbo-
  114.          Pascal standard procedure exit may be used); this routine is
  115.          provided as a sort of `replacement' for the C return statement }
  116.      procedure echo;
  117.        { echo the matched token in yytext to the output } *)
  118.  
  119.   implementation
  120.   {$I-}
  121.  
  122.   var nextExitProc : Pointer;
  123.     (* pointer to next exit procedure *)
  124.   {$F+}
  125.   procedure yylexit;
  126.   {$F-}
  127.     (* LexLib exit procedure; MUST be called FAR *)
  128.     begin
  129.       close(yyin); if ioresult<>0 then ;
  130.       close(yyout); if ioresult<>0 then ;
  131.       exitProc := nextExitProc (* chain to next exit procedure *)
  132.     end(*yylexit*);
  133.   (* character codes: *)
  134.   const
  135.     LF = #10; (* line feed *)
  136.     CR = #13; (* carriage return *)
  137.     NEWLINE = LF; (* newline character *)
  138.  
  139.   (* The default I/O streams are implemented in terms of the text files
  140.      yyin and yyout. unput is implemented via a string buffer
  141.      yybuf.
  142.      input needs lookahead itself in order to determine line ends <CR><LF>;
  143.      this lookahead is also handled with unput. *)
  144.   var
  145.     yybuf : string;
  146.     yybufleng : Byte absolute yybuf;
  147.     (* buffer holding input to be reread (unput) *)
  148.   function input : char;
  149.     var c : char;
  150.     begin
  151.       if yybufleng>0 then
  152.         begin
  153.           if yybuf[yybufleng]=NEWLINE then
  154.             inc(yylineno);
  155.           input := yybuf[yybufleng];
  156.           dec(yybufleng)
  157.         end
  158.       else if eof(yyin) then
  159.         input := #0
  160.       else
  161.         begin
  162.           read(yyin, c);
  163.           yyioresult := ioresult;
  164.           if yyioresult<>0 then
  165.             input := #0
  166.           else if (c=CR) and not eof(yyin) then
  167.             begin
  168.               read(yyin, c);
  169.               if c=LF then
  170.                 begin
  171.                   inc(yylineno);
  172.                   input := NEWLINE
  173.                 end
  174.               else
  175.                 begin
  176.                   unput(c);
  177.                   input := CR
  178.                 end
  179.             end
  180.           else
  181.             input := c;
  182.         end;
  183.       yyioresult := ioresult;
  184.       if yyioresult<>0 then
  185.         input := #0
  186.     end(*input*);
  187.   procedure output(c : char);
  188.     begin
  189.       if c=NEWLINE then
  190.         (* convert NEWLINE to <CR><LF> *)
  191.         write(yyout, CR, LF)
  192.       else
  193.         write(yyout, c);
  194.       yyioresult := ioresult
  195.     end(*output*);
  196.   procedure unput(c : char);
  197.     begin
  198.       if yybufleng=255 then
  199.         if yyloverflow then halt(1) else
  200.       else
  201.         begin
  202.           inc(yybufleng);
  203.           yybuf[yybufleng] := c;
  204.           if c=NEWLINE then
  205.             dec(yylineno)
  206.         end
  207.     end(*unput*);
  208.   function yywrap : boolean;
  209.     begin
  210.       yywrap := true
  211.     end(*yywrap*);
  212.   function yyloverflow : boolean;
  213.     begin
  214.       writeln('yylex: buffer overflow');
  215.       yyloverflow := true
  216.     end(*yyloverflow*);
  217.   begin
  218.     (* obtain current exit procedure chain: *)
  219.     nextExitProc := exitProc;
  220.     (* install LexLib exit procedure: *)
  221.     exitProc := @yylexit;
  222.     (* assign yyin and yyout to stdin and stdout, respectively *)
  223.     assign(yyin, ''); assign(yyout, '');
  224.     reset(yyin); rewrite(yyout);
  225.     yyioresult := ioresult;
  226.     yybuf := '';
  227.     yylineno := 1
  228.   end(*LexLib*).